using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace MKDS_Course_Editor
{
    public partial class spa : Form
    {
        SPA sp;
        Color[] palette = new Color[256];
        Color[] palette_org = new Color[256];
        string file;
        public spa(string file)
        {
            this.file = file;
            InitializeComponent();
            int colorNum = 0;
            for (int r = 0; r < 256; r += 256 / 8)
                for (int g = 0; g < 256; g += 256 / 8)
                    for (int b = 0; b < 256; b += 256 / 4)
                        palette[colorNum++] = Color.FromArgb(r, g, b);
            palette_org = palette;
        }

        private void spa_Load(object sender, EventArgs e)
        {
            EndianBinaryReader er = new EndianBinaryReader(new MemoryStream(File.ReadAllBytes(file)), Endianness.LittleEndian);
            sp = new SPA();
            sp.Magic = er.ReadString(Encoding.ASCII, 4);
            if (sp.Magic == " APS")
            {
                er.ReadBytes(0x6);
                sp.nrTPS = er.ReadInt16();
                er.ReadBytes(0xc);
                sp.offTPS = er.ReadInt32();
                sp.TPS = new SPA.tps[sp.nrTPS];
                er.BaseStream.Seek(sp.offTPS, SeekOrigin.Begin); //jump to start of TPS
                for (int i = 0; i < sp.nrTPS; i++)
                {
                    sp.TPS[i].Magic = er.ReadString(Encoding.ASCII, 4);
                    if (sp.TPS[i].Magic == " TPS")
                    {
                        //sp.TPS[i].havePal = (er.ReadByte() == 1 ? true : false);
                        er.ReadBytes(4);
                        sp.TPS[i].nrBytes = er.ReadInt32();
                        er.ReadBytes(1);
                        sp.TPS[i].bpp = er.ReadByte();
                        er.ReadBytes(2);
                        sp.TPS[i].Pallength = er.ReadInt32();
                        er.ReadBytes(0x08);
                        sp.TPS[i].Length = er.ReadInt32();
                        sp.TPS[i].Image = er.ReadBytes(sp.TPS[i].nrBytes);
                        //byte[] b = er.ReadBytes(1);
                        //List<Color> pal = new List<Color>();
                        //int color = 1;
                        //while (er.ReadByte() != 0x7F)
                        //{
                        //   er.BaseStream.Position -= 1;
                        //    pal.AddRange(Tinke.Convertir.BGR555(er.ReadBytes(2)));
                        //    color += 2;
                        sp.TPS[i].pal = Tinke.Convertir.BGR555(er.ReadBytes(sp.TPS[i].Pallength));// - 2 - (sp.TPS[i].Length - 32 - sp.TPS[i].nrBytes - sp.TPS[i].Pallength)));//sp.TPS[i].Length - 32 - sp.TPS[i].nrBytes)/*.Reverse<byte>().ToArray<byte>()*/);
                        if (sp.TPS[i].pal[sp.TPS[i].pal.Length - 1].Name == "ff000000")
                        {
                            List<Color> pal = new List<Color>();
                            pal.AddRange(sp.TPS[i].pal);
                            pal.RemoveAt(sp.TPS[i].pal.Length - 1);
                            sp.TPS[i].pal = pal.ToArray();
                        }
                        //}
                        //er.BaseStream.Position -= 1;
                        //er.ReadBytes(sp.TPS[i].Pallength - color);
                        //sp.TPS[i].pal = pal.ToArray();
                        for (int k = 0; k < sp.TPS[i].pal.Length; k++)
                        {
                            //sp.TPS[i].pal[k] = InvertMeAColour(sp.TPS[i].pal[k]);
                        }
                        //er.BaseStream.Seek(sp.TPS[i].Length - 32 - sp.TPS[i].nrBytes, SeekOrigin.Current);
                        //if (sp.TPS[i].havePal == false)
                        //{
                            if (palette == palette_org)
                            {
                                palette = sp.TPS[i].pal;
                            }
                            else
                            {
                                List<Color> c = new List<Color>();
                                c.AddRange(palette);
                                c.AddRange(sp.TPS[i].pal);
                                palette = c.ToArray();
                            }
                        //}
                        listBox1.Items.Add("Item " + (i+1).ToString());
                    }
                    else
                    {
                        MessageBox.Show("Error");
                        er.Close();
                    }
                }
                er.Close();

            }
            else
            {
                MessageBox.Show("Error");
                er.Close();
            } 
        }
        const int RGBMAX = 255;

        Color InvertMeAColour(Color ColourToInvert)
        {
            return Color.FromArgb(RGBMAX - ColourToInvert.R,
              RGBMAX - ColourToInvert.G, RGBMAX - ColourToInvert.B);
        } 

        public struct SPA
        {
            public String Magic;
            public Int16 nrTPS;
            public tps[] TPS;
            public Int32 offTPS;
            public struct tps
            {
                public String Magic;
                public Int32 nrBytes;
                public Int32 Length;
                public Int32 Pallength;
                public byte[] Image;
                public Color[] pal;
                public byte bpp;
                //public bool havePal;
            }
        }

        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (palette.Length != 0)
            {
                //palette = sp.TPS[listBox1.SelectedIndex].pal;
            }
            //nclr_e c = new nclr_e(palette, true, 0);
            //c.ShowDialog();
            bool use4bpp = false;
            byte[] file2 = sp.TPS[listBox1.SelectedIndex].Image;
            int TileCount = file2.Length / (use4bpp ? 32 : 64);
            if (TileCount == 0)
                return;
            //try
            //{
            if(sp.TPS[listBox1.SelectedIndex].bpp == 4)
            {
                Bitmap TileBuffer = new Bitmap(TileCount * (sp.TPS[listBox1.SelectedIndex].Pallength == 4 ? 4 : 2), TileCount * (sp.TPS[listBox1.SelectedIndex].Pallength == 4 ? 4 : 2));

                int FilePos = 0;
                for (int i = 0; i < 1; i++)
                {
                    for (int TileY = 0; TileY < TileCount * (sp.TPS[listBox1.SelectedIndex].Pallength == 4 ? 4 : 2); TileY++)
                    {
                        for (int TileX = 0; TileX < TileCount * (sp.TPS[listBox1.SelectedIndex].Pallength == 4 ? 4 : 2); TileX++)
                        {
                            TileBuffer.SetPixel(TileX, TileY, gpalette(file2[FilePos] + (int)listBox1.SelectedIndex * 16));
                            FilePos++;
                        }
                    }
                }
                pictureBox1.Image = TileBuffer;
            }
            else
            {
                Bitmap TileBuffer = new Bitmap(TileCount, TileCount);

                int FilePos = 0;
                for (int i = 0; i < 1; i++)
                {
                    for (int TileY = 0; TileY < TileCount; TileY++)
                    {
                        for (int TileX = 0; TileX < TileCount; TileX++)
                        {
                            TileBuffer.SetPixel(TileX, TileY, gpalette(file2[FilePos] + (int)0 * 256));
                            FilePos++;
                        }
                    }
                }
                pictureBox1.Image = TileBuffer;
            }
        }
        private Color gpalette(int n)
        {
            if (n >= palette.Length)
                return Color.Pink;
            return palette[n];
        }
        public static Bitmap CutImage(Image im, int width, int blockrows)
        {
            int blocksize = im.Height / blockrows;
            int blockcount = im.Width / blocksize;

            int cols = width / blocksize;
            int rows = blockcount / cols;

            Bitmap b = new Bitmap(cols * blocksize, rows * blocksize * blockrows);
            Graphics g = Graphics.FromImage(b);
            g.Clear(Color.Gray);

            Rectangle SourceRect = new Rectangle(0, 0, cols * blocksize, blocksize);
            Rectangle DestRect = new Rectangle(0, 0, cols * blocksize, blocksize);


            for (int r = 0; r < blockrows; r++)
            {
                SourceRect.Y = r * blocksize;
                for (int i = 0; i < rows; i++)
                {
                    SourceRect.X = i * cols * blocksize;
                    DestRect.Y = i * blocksize + r * rows * blocksize;

                    g.DrawImage(im, DestRect, SourceRect, GraphicsUnit.Pixel);
                }
            }

            return b;
        }
    }
}
